from flask import request, g
from app.metrics.jwt_token import JwtToken, JwtTokenError
from app.metrics.signature_tool import Signature
from app.metrics.permission_arrange import permission_detect
from app.err_no import errno_no
from app.settings.base import super_administrator
from app.db.dbUserLogin import getDiningsByUserId
from loguru import logger
import traceback

jwtToken = JwtToken()
signObj = Signature()

'''
AES加密: CBC, utf-8, pkcs7
aes在线: http://tool.chacuo.net/cryptaes
md5在线: http://www.metools.info/code/c26.html
base64在线：https://tool.ip138.com/base64/
json在线压缩：https://www.bejson.com/zhuanyi/
'''


def filter_TokenSignModulePermission(requestData, endpoint):
    '''
    统一鉴权接口
        1. 身份验证：验证身 token
        2. 数字签名：验证数据合法性
        3. 检验用户是否有权限调用某个接口
    '''
    token = request.headers.get('token')
    sign = request.headers.get('sign')
    if token is None or len(token) <= 0 \
        or sign is None or len(sign) <= 0:
        logger.error(f'鉴权失败:缺少token or sign')
        return errno_no.ErrServerTokenSign.data(None)
    try:
        userInfo = jwtToken.verifyToken(token)
        bSign, serSign = signObj.verifySign(sign, requestData)
        if not bSign:
            logger.error(f'鉴权失败,数字签名错误: recvSign={sign}, serverSign={serSign}')
            return errno_no.ErrServerTokenSign.data(None)

        userId = userInfo.get('userId')
        userRoleId = userInfo.get('userRoleId')
        userRoleName = userInfo.get('userRoleName')
        #
        bAuthorization, rolePower = permission_detect(endpoint, userRoleId)
        if not bAuthorization:
            logger.error(f'鉴权失败,权限不足: userRoleId={userRoleId}, userId={userId}, endpoint={endpoint}, rolePower={rolePower}')
            return errno_no.ErrServerPermissionDenied.data(None)

        RelationStallNo = userInfo.get('RelationStallNo')
        #print('~~',RelationStallNo)
        # 全部 all or 餐厅 dining or 档口 stall
        if userRoleName == super_administrator:
            userType = 'all'
        elif RelationStallNo is not None and len(RelationStallNo) > 0:
            userType = 'stall'
        else:
            userType = 'dining'

        g.userId = userId
        g.userRoleId = userRoleId
        g.userRoleName = userRoleName
        g.userType = userType
        g.RelationStallNo = RelationStallNo
        if userType == 'dining':
            g.RelationDiningNoList = getDiningsByUserId(userId)
        
    except JwtTokenError as e:
        logger.error(f'鉴权失败,token异常:{e.__dict__},traceback={traceback.format_exc()}')
        if 'token expires' == str(e):
            return errno_no.ErrServerTokenExpires.data(None)
        else:
            return errno_no.ErrServerTokenSign.data(None)

    except Exception as e:
        logger.error(f'鉴权失败,其他异常:{e.__dict__},traceback={traceback.format_exc()}')
        return errno_no.ErrServerTokenSign.data(None)

    return None


def filter_onlyNeedSign(requestData):
    '''
    统一鉴权接口
        1. 数字签名：验证数据合法性
    '''
    sign = request.headers.get('sign')
    if sign is None or len(sign) <= 0:
        logger.error(f'鉴权失败:缺少token or sign')
        return errno_no.ErrServerTokenSign.data(None)
    try:
        # 验证数字签名
        bSign, serSign = signObj.verifySign(sign, requestData)
        if not bSign:
            logger.error(f'鉴权失败,数字签名错误: recvSign={sign}, serverSign={serSign}')
            return errno_no.ErrServerTokenSign.data(None)

    except Exception as e:
        logger.error(f'鉴权失败,Exception异常:{e.__dict__},traceback={traceback.format_exc()}')
        return errno_no.ErrServerTokenSign.data(None)

    return None


def filter_onlyNeedTokenSign(requestData):
    '''
    仅需要登录成功即可调用的接口
        1. 身份验证：验证身 token
        2. 数字签名：验证数据合法性
    '''
    token = request.headers.get('token')
    sign = request.headers.get('sign')
    if token is None or len(token) <= 0 \
        or sign is None or len(sign) <= 0:
        logger.error(f'鉴权失败:缺少token or sign')
        return errno_no.ErrServerTokenSign.data(None)
    try:
        userInfo = jwtToken.verifyToken(token)
        bSign, serSign = signObj.verifySign(sign, requestData)
        if not bSign:
            logger.error(f'鉴权失败,数字签名错误: recvSign={sign}, serverSign={serSign}')
            return errno_no.ErrServerTokenSign.data(None)

        userId = userInfo.get('userId')
        userRoleId = userInfo.get('userRoleId')
        userRoleName = userInfo.get('userRoleName')

        RelationStallNo = userInfo.get('RelationStallNo')
        #print('~~',RelationStallNo)
        # 全部 all or 餐厅 dining or 档口 stall
        if userRoleName == super_administrator:
            userType = 'all'
        elif RelationStallNo is not None and len(RelationStallNo) > 0:
            userType = 'stall'
        else:
            userType = 'dining'

        g.userId = userId
        g.userRoleId = userRoleId
        g.userRoleName = userRoleName
        g.userType = userType
        g.RelationStallNo = RelationStallNo
        if userType == 'dining':
            g.RelationDiningNoList = getDiningsByUserId(userId)
        
    except JwtTokenError as e:
        logger.error(f'鉴权失败,token异常:{e.__dict__},traceback={traceback.format_exc()}')
        if 'token expires' == str(e):
            return errno_no.ErrServerTokenExpires.data(None)
        else:
            return errno_no.ErrServerTokenSign.data(None)

    except Exception as e:
        logger.error(f'鉴权失败,其他异常:{e.__dict__},traceback={traceback.format_exc()}')
        return errno_no.ErrServerTokenSign.data(None)

    return None


def filter_TokenModulePermission(endpoint):
    '''
    统一鉴权接口
        1. 身份验证：验证身 token
        2. 检验用户是否有权限调用某个接口
    '''
    token = request.headers.get('token')
    if token is None or len(token) <= 0:
        logger.error(f'鉴权失败:缺少token or sign')
        return errno_no.ErrServerTokenSign.data(None)
    try:
        userInfo = jwtToken.verifyToken(token)
        userId = userInfo.get('userId')
        userRoleId = userInfo.get('userRoleId')
        userRoleName = userInfo.get('userRoleName')
        #
        bAuthorization, rolePower = permission_detect(endpoint, userRoleId)
        if not bAuthorization:
            logger.error(f'鉴权失败,权限不足: userRoleId={userRoleId}, userId={userId}, endpoint={endpoint}, rolePower={rolePower}')
            return errno_no.ErrServerPermissionDenied.data(None)

        RelationStallNo = userInfo.get('RelationStallNo')
        #print('~~',RelationStallNo)
        # 全部 all or 餐厅 dining or 档口 stall
        if userRoleName == super_administrator:
            userType = 'all'
        elif RelationStallNo is not None and len(RelationStallNo) > 0:
            userType = 'stall'
        else:
            userType = 'dining'

        g.userId = userId
        g.userRoleId = userRoleId
        g.userRoleName = userRoleName
        g.userType = userType
        g.RelationStallNo = RelationStallNo
        if userType == 'dining':
            g.RelationDiningNoList = getDiningsByUserId(userId)
        
    except JwtTokenError as e:
        logger.error(f'鉴权失败,token异常:{e.__dict__},traceback={traceback.format_exc()}')
        if 'token expires' == str(e):
            return errno_no.ErrServerTokenExpires.data(None)
        else:
            return errno_no.ErrServerTokenSign.data(None)

    except Exception as e:
        logger.error(f'鉴权失败,其他异常:{e.__dict__},traceback={traceback.format_exc()}')
        return errno_no.ErrServerTokenSign.data(None)

    return None